--- 'https://github.com/Frege/frege/issues/278 Sigma problems'
module tests.comp.Issue278 where

import Data.List

problem1 ∷ (forall a. a->a) -> a -> b -> (a,b)
--                    ^^^^              bound type variable(s) a not appearing in type
problem1 f x y = (f x, f y)



import frege.data.wrapper.Const 
import frege.data.wrapper.Identity

type Lens s a = forall f. Functor f => (a -> f a) -> s -> f s

view :: Lens s a -> (s -> a)
view lens = Const.get . lens Const

set :: Lens s a -> (a -> s -> s)
set lens x = over lens (const x)

over :: Lens s a -> (a -> a) -> s -> s
over lens f = Identity.run . lens (Identity . f)

data Bank       = Bank      { client    :: Client     }
data Client     = Client    { portfolio :: Portfolio  }
data Portfolio  = Portfolio { position  :: Position   }
data Position   = Position  { soMany    :: Int        }

soManyLens        :: Lens Position Int
soManyLens f p    = fmap  p.{soMany =} (f p.soMany)

positionLens      :: Lens Portfolio Position
positionLens f p  = fmap p.{position =} (f p.position)

portfolioLens     :: Lens Client Portfolio
portfolioLens f c = fmap c.{portfolio =} (f c.portfolio)

clientLens        :: Lens Bank Client
clientLens f b    = fmap b.{client =} (f b.client)

derive Show Bank
derive Show Client
derive Show Portfolio
derive Show Position

bank = Bank {
    client = Client {
        portfolio = Portfolio {
            position = Position { soMany = 0 }
        }
    }
}

main _ = do    
    position  = Position  0
    portfolio = Portfolio position
    println $ view soManyLens      position
    println $ set  soManyLens   1  position
    println $ over soManyLens (+2) position

    println $ view (positionLens . soManyLens)      portfolio
    println $ set  (positionLens . soManyLens)   3  portfolio
    println $ over (positionLens . soManyLens) (+4) portfolio

    let deepLens ∷ Functor f => (Int→f Int)→Bank→f Bank
        deepLens = clientLens . portfolioLens . positionLens . soManyLens
    println $ view deepLens bank
    println $ set  deepLens   5  bank
    println $ over deepLens (+6) bank
    